﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using DownloadBook.Server;

namespace DownloadBook {
    public partial class FrmMain : Form {
        private string m_OriginTitle;
        private List<Content> m_ContentList = new List<Content>();
        private DownloadContent downloadContent;
        public FrmMain() {
            InitializeComponent();
        }

        private void FrmMain_Load(object sender, EventArgs e) {
            ThreadPool.SetMinThreads(30, 10);
            SelectAllSupport.Bind(txtOriginHtml);
            SelectAllSupport.Bind(txtBookName);
            SelectAllSupport.Bind(txtURL);

            m_OriginTitle = this.Text;
            comMaxThreadCount.SelectedItem = "10";
            lblMsg.Text = "准备就绪";
        }

        private void BtnDownloadHtml_Click(object sender, EventArgs e) {
            string url = txtURL.Text;
            if (string.IsNullOrEmpty(url)) {
                ShowErrorMsg("Url不能为空");
            }else {
                NewThreadTask(() => {
                    string html =  HttpGet.httpGet(url);
                    this.Invoke( new EventHandler(delegate {
                        txtOriginHtml.Text = html;
                    }));
                });
            }
        }
        

        private void btnExtractMenuItem_Click(object sender, EventArgs e) {
            if (string.IsNullOrEmpty(txtURL.Text)) {
                ShowErrorMsg("请先输入URL");
            } else {
                Regex regex = new Regex("<a[^>]*?>([\\w\\W]*?)</a>", RegexOptions.IgnoreCase);
                int groupId = 0;
                Match match = regex.Match(txtOriginHtml.Text);
                if (!match.Success) {
                    lblMsg.Text = "提取失败，请重新设置提取目录的正则表达式";
                } else if (match.Groups.Count < groupId) {
                    lblMsg.Text = "提取失败，分组不够，分组id不正确";
                } else {
                    m_ContentList.Clear();
                    listMenuItemList.Items.Clear();

                    string originUrl = txtURL.Text;
                    while (match.Success) { 
                        string item = match.Groups[groupId].ToString();

                        string href = HtmlUtil.GetAHref(item);
                        string url = HtmlUtil.linkCalculation(originUrl, href);
                        string title = HtmlUtil.GetAText(item);
                        Content content = new Content();
                        content.title = title;
                        content.url = url;


                        m_ContentList.Add(content);
                        match = match.NextMatch();
                    }
                    SearchMenuItem();
                }
                MessageBox.Show(string.Format("提取完成，一共{0}个元素", m_ContentList.Count) , "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        /// <summary>
        /// 搜索目录按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSearchMenuItem_Click(object sender, EventArgs e) {
            SearchMenuItem();
        }


        private void btnDownloadContext_Click(object sender, EventArgs e) {
            if (this.m_ContentList.Count < 1) {
                ShowErrorMsg("请先提取章节目录元素");
            } else {
                int maxThreadCount = Math.Max(1, Convert.ToInt32(comMaxThreadCount.Text));
                string bookName = txtBookName.Text;
                string url = txtURL.Text;
                this.Text = string.Format("{0} - {1}", bookName, m_OriginTitle);
                NewThreadTask(() => {
                    DownloadContent(bookName, url, maxThreadCount);
                });
            }
        }
        private readonly Book book = new Book();

        private void btnMergeContent_Click(object sender, EventArgs e) {
            if (string.IsNullOrEmpty(txtURL.Text)) {
                ShowErrorMsg("请先输入网址");
            } else if (string.IsNullOrEmpty(txtBookName.Text)) {
                ShowErrorMsg("请先输入书名");
            } else if (m_ContentList.Count < 1) {
                ShowErrorMsg("请先提取章节目录元素");
            } else {
                book.name = txtBookName.Text;
                book.url = txtURL.Text;
                book.contentList = m_ContentList;
                book.htmlDirectory = GetDownloadTempDirectory(txtBookName.Text);
                FrmMergeContent frmMergeContent = new FrmMergeContent(book);
                frmMergeContent.ShowDialog();
            }
        }

        private void AlertDownloadState(bool isDownloading) {
            this.Invoke(new EventHandler(delegate {
                bool enabled = !isDownloading;
                this.btnDownloadContext.Enabled = enabled;
                this.BtnDownloadHtml.Enabled = enabled;
                this.comMaxThreadCount.Enabled = enabled;
                this.btnExtractMenuItem.Enabled = enabled;
                this.txtBookName.Enabled = enabled;
                this.txtURL.Enabled = enabled;
            }));

        }

        /// <summary>
        /// 下载章节列表
        /// </summary>
        private void DownloadContent(string bookName, string url, int maxThreadCount) {
            if (string.IsNullOrEmpty(bookName)) {
                ShowErrorMsg("请先输入书名");
            }else {
                AlertDownloadState(true);
                string directory = GetDownloadTempDirectory(bookName);
                bool submiting = false;
                string lastMsg = "";

                DownloadContent.UpdateMessage actionUpdateLblMsgText = (string msg) => {
                    lock (this) {
                        lastMsg = msg;
                        if (!submiting) {
                            submiting = true;
                            this.BeginInvoke(new EventHandler(delegate {
                                lock (this) {
                                    submiting = false;
                                    lblMsg.Text = lastMsg;
                                }
                            }));
                        }
                    }
                };

                actionUpdateLblMsgText("准备开始下载");

                downloadContent = new DownloadContent(directory, url, m_ContentList, maxThreadCount, actionUpdateLblMsgText, ()=> {
                    AlertDownloadState(false);
                });
                downloadContent.Start();
            }
        }

        private void btnStopDownload_Click(object sender, EventArgs e) {
            if (downloadContent != null) {
                downloadContent.Stop();
            }
        }

        private string GetDownloadTempDirectory(string bookName) {
            string tempDirectory = Path.Combine(Environment.CurrentDirectory, "Temp");
            return Path.Combine(tempDirectory, bookName);
        }

        

        private void NewThreadTask(Action action) {
            Thread thread = new Thread(new ThreadStart(action));
            thread.IsBackground = true;
            thread.Start();
        }

        private void ShowErrorMsg(string msg) {
            ShowErrorMsg(msg, "出错了");
        }
        private void ShowErrorMsg(string msg, string title) {
            MessageBox.Show(msg, title, MessageBoxButtons.OK, MessageBoxIcon.Error);

        }


        private void SearchMenuItem() {
            if (chkHideNotExistsInSearchResurt.Checked) {
                ShowSearchMenuItemsHideNotExistResult();
            } else {
                ShowSearchMenuItemsOnlySelected();
            }
        }

        /// <summary>
        /// 显示搜索结果，隐藏不在搜索结果中的对象
        /// </summary>
        private void ShowSearchMenuItemsHideNotExistResult() {
            string searchKey = txtSearchMenuItem.Text;
            listMenuItemList.Items.Clear();
            listMenuItemList.ClearSelected();

            if (!string.IsNullOrEmpty(searchKey)) {
                for (int i = 0; i < m_ContentList.Count; i++) {
                    Content content = m_ContentList[i];
                    if (content.title.Contains(searchKey)) {
                        listMenuItemList.Items.Add(content);
                        listMenuItemList.SetSelected(listMenuItemList.Items.Count - 1, true);
                    }
                }
            }
        }


        /// <summary>
        /// 显示搜索结果，只选中，不移除
        /// </summary>
        private void ShowSearchMenuItemsOnlySelected() {
            string searchKey = txtSearchMenuItem.Text;
            listMenuItemList.Items.Clear();
            listMenuItemList.ClearSelected();
            for (int i = 0; i < m_ContentList.Count; i++) {
                Content content = m_ContentList[i];
                listMenuItemList.Items.Add(content);
                if (!string.IsNullOrEmpty(searchKey)) {//如果有输入搜索内容
                    if (content.title.Contains(searchKey)) {
                        listMenuItemList.SetSelected(i, true);
                    }
                }
            }
        }

        private void listMenuItemList_KeyDown(object sender, KeyEventArgs e) {
            if (e.KeyCode == Keys.Delete) {
                RemoveSelectedMenuItem();
            }
        }

        /// <summary>
        /// 移除选中的目录元素
        /// </summary>
        private void RemoveSelectedMenuItem() {
            int removeItemCount = listMenuItemList.SelectedItems.Count;
            if (removeItemCount > 0) {
                string title = "删除提示";
                string text;
                if (removeItemCount == 1) {
                    text = string.Format("您确定要删除章节：{0} 吗？", listMenuItemList.SelectedItem);
                } else {
                    text = "您确定要移除选中的章节列表吗？选中的章节个数：" + removeItemCount;
                }
                if (DialogResult.Yes == MessageBox.Show(text, title, MessageBoxButtons.YesNo, MessageBoxIcon.Information)) {
                    while(listMenuItemList.SelectedItems.Count > 0) { 
                        object item = listMenuItemList.SelectedItems[0];
                        listMenuItemList.Items.Remove(item);
                        m_ContentList.Remove(item as Content);
                    }
                }
            }
        }

        /// <summary>
        /// 菜单 - 目录元素删除选中的元素
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuItemDeleteSelectedToolStripMenuItem_Click(object sender, EventArgs e) {
            RemoveSelectedMenuItem();
        }

        /// <summary>
        /// 菜单 - 浏览器中打开原始链接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuOpenOriginURL_Click(object sender, EventArgs e) {
            if(listMenuItemList.SelectedItems.Count == 1) {
                Content content = listMenuItemList.SelectedItem as Content;
                if(content != null) {
                    Process.Start("explorer.exe", content.url);
                }
            }
        }

        /// <summary>
        /// 目录元素列表窗口右键菜单加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void contextMenuListMenuItemSearchResult_Opening(object sender, CancelEventArgs e) {
            int selectedItemCount = listMenuItemList.SelectedItems.Count;
            int itemsCount = listMenuItemList.Items.Count;
            bool selectedOne = selectedItemCount == 1;
            //只选择一个元素时可用的菜单
            menuOpenOriginURL.Enabled = selectedOne;//打开原始URL，只选一个章节时可用
            menuItemDeleteSelectedToolStripMenuItem.Enabled = selectedItemCount > 0;//删除。有选择才能用
            menuCopyTitleToolStripMenuItem.Enabled = selectedOne;//复制标题

            //全选 - 反选 - 全不选
            menuSelectAllToolStripMenuItem.Enabled = itemsCount > 0 && selectedItemCount < itemsCount;//全选，有元素并且还未全选时可用
            menuSelectAllNotToolStripMenuItem.Enabled = itemsCount > 0 && selectedItemCount > 0;//全不选，有元素并且有选择了才可用
            menuSelectReverseToolStripMenuItem.Enabled = itemsCount > 0;//反选，只要有元素就可用

            //向上选择、向下选择
            menuSelectToStartToolStripMenuItem.Enabled = selectedOne;//向上选择到开始
            menuSelectToEndToolStripMenuItem.Enabled = selectedOne;//向下选择到结束
        }

        /// <summary>
        /// 菜单 - 全选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuSelectAllToolStripMenuItem_Click(object sender, EventArgs e) {
            for(int i = 0; i < listMenuItemList.Items.Count; i++) {
                listMenuItemList.SetSelected(i, true);
            }
        }

        /// <summary>
        /// 菜单 - 反选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuSelectReverseToolStripMenuItem_Click(object sender, EventArgs e) {
            for (int i = 0; i < listMenuItemList.Items.Count; i++) {
                listMenuItemList.SetSelected(i, !listMenuItemList.GetSelected(i));//切换选中状态
            }
        }

        /// <summary>
        /// 菜单 - 全不选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuSelectAllNotToolStripMenuItem_Click(object sender, EventArgs e) {
            listMenuItemList.ClearSelected();
        }

        /// <summary>
        /// 菜单 - 向上选择到开始
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuSelectToStartToolStripMenuItem_Click(object sender, EventArgs e) {
            int endIndex = listMenuItemList.SelectedIndex;
            for (int i = 0; i < endIndex; i++) {
                listMenuItemList.SetSelected(i, true);
            }
        }

        /// <summary>
        /// 菜单 - 向下选择到结束
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuSelectToEndToolStripMenuItem_Click(object sender, EventArgs e) {
            for (int i = listMenuItemList.SelectedIndex + 1; i < listMenuItemList.Items.Count; i++) {
                listMenuItemList.SetSelected(i, true);
            }
        }
        
        /// <summary>
        /// 菜单 - 复制标题
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuCopyTitleToolStripMenuItem_Click(object sender, EventArgs e) {
            if(listMenuItemList.SelectedItems.Count == 1) {
                Content content = listMenuItemList.SelectedItem as Content;
                if(content != null) {
                    Clipboard.Clear();
                    Clipboard.SetText(content.title);
                }
            }
        }


        /// <summary>
        /// 菜单 - 关于
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lblAbout_Click(object sender, EventArgs e) {
            string url = "https://gitee.com/fjqingyou/DownloadBook/issues";
            Process.Start(url);
        }

        /// <summary>
        /// 本地搜索 回车键支持
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtSearchMenuItem_KeyUp(object sender, KeyEventArgs e) {
            if (e.KeyCode == Keys.Enter) {
                btnSearchMenuItem.PerformClick();//模拟点击按钮
            }
        }


    }
}
